import moment from 'moment';
import { TRMessage } from '#/components';
import { HttpCode } from '#/utils/contacts.js';
import {
  fetchTradeTime,
  fetchSequencesFuture,
  fetchSequences,
  fetchPrograms,
  fetchUnitStatus,
  fetchHourOrderInfo,
  cancelTimelySubmit,
  fetchSequencesLimit,
  fetchOverviewProgramToBeSubmited,
  saveUnits,
  submit,
  updateStatus,
  fetchLatestLog,
  deleteProgram,
  queryMarketList,
} from '@/pages/Tianji/RollingBatch/services';
import {
  emptyIfNotExist,
  findFirstIfArr,
  objHasElement,
  findDefaultProgramId,
  clone,
  getNewProgramName,
  getNewProgramInfo,
  selectedUnitsHasModified,
  getButtonPermission,
  arrHasElement,
  getUnitPowerLimitInfo,
  get24HourLimitList,
} from './utils';
import { PROGARM_STATUS } from './constant/enums';
import messageConstant from './constant/message';
import {
  SEQUENCE_TRADE_TIME_PATTERN,
  PROGRAM_NOT_EXIST_HTTP_CODE,
  PROGRAM_LOCKED_HTTP_CODE,
  PROGRAM_NOT_TIMELY_HTTP_CODE,
} from './constant';
import { getTreeByCodes } from '@/utils/index.js';

let timeout;
const delay = (time) => new Promise((resolve) => setTimeout(resolve, time));
const delayClear = (time) =>
  new Promise((resolve) => {
    clearTimeout(timeout);
    timeout = setTimeout(resolve, time);
  });

export default {
  namespace: 'rollingBatch',
  state: {
    // 交易中心时间
    tradeCenterTime: null,
    // 是否修改过
    hasModified: false,
    // 全局loading
    loadingNum: 0,
    // Main组件是否显示
    showMain: false,
    // 选择的时点行
    selectedRowKeys: [],
    // 场站权限树
    unitTree: [],
    // 根据unitTree整理
    componentUnitList: [],
    // 序列信息
    globalSequence: {
      date: new moment(),
      dataList: [],
      current: {},
      selected: {},
    },
    // 限价信息，key：序列id，value：24时段限价列表
    priceLimitInfo: {},
    // 当前序列的限额信息，key场站id，value： key：时段1-24，value限额信息
    powerLimitInfo: {},
    // 方案列表
    programList: [],
    // 用户有权限的场站限额列表
    unitPowerLimitList: [],
    // 用户有权限的场站挂单状态列表
    unitResultList: [],
    // 状态查询更新时间
    statusUpdateTime: '',
    // 方案总览列表
    programOverviewList: [],

    /**  当前方案信息  */
    // 当前方案所选场站
    currentUnitList: [],
    // 当前方案最新的操作日志
    latestOperateLog: {},
    // 当前方案的权限
    currentProgramPermission: {
      remove: false,
      modify: false,
      export: false,
      save: false,
      timely: false,
      submit: false,
    },
    // 当前方案的时段列表
    currentProgramHourOrderList: [],
    // 当前方案基本信息
    currentProgramInfo: {},
  },
  reducers: {
    setPowerLimitInfo(state, { payload }) {
      return { ...state, powerLimitInfo: payload };
    },
    setCurrentUnitList(state, { payload }) {
      return { ...state, currentUnitList: payload };
    },
    setLatestOperateLog(state, { payload }) {
      return { ...state, latestOperateLog: payload };
    },
    setCurrentProgramPermisson(state, { payload }) {
      return { ...state, currentProgramPermission: payload };
    },
    setCurrentProgramHourOrderList(state, { payload }) {
      return { ...state, currentProgramHourOrderList: payload };
    },
    setCurrentProgramInfo(state, { payload }) {
      return { ...state, currentProgramInfo: payload };
    },

    setUnitTree(state, { payload }) {
      return { ...state, unitTree: payload };
    },
    setComponentUnitList(state, { payload }) {
      return { ...state, componentUnitList: payload };
    },
    setProgramOverviewList(state, { payload }) {
      return { ...state, programOverviewList: payload };
    },
    setTradeCenterTime(state, { payload }) {
      return { ...state, tradeCenterTime: payload };
    },
    setAddLoadingNum(state) {
      return { ...state, loadingNum: state.loadingNum + 1 };
    },
    setSubLoadingNum(state) {
      return { ...state, loadingNum: state.loadingNum - 1 };
    },
    setShowMain(state, { payload }) {
      return { ...state, showMain: payload };
    },
    setHasModified(state, { payload }) {
      return { ...state, hasModified: payload };
    },
    setSelectedRowKeys(state, { payload }) {
      return { ...state, selectedRowKeys: payload };
    },
    setGlobalSequence(state, { payload }) {
      return { ...state, globalSequence: { ...state.globalSequence, ...payload } };
    },
    setPriceLimitInfo(state, { payload }) {
      return { ...state, priceLimitInfo: { ...state.priceLimitInfo, ...payload } };
    },
    setProgramList(state, { payload }) {
      return { ...state, programList: payload };
    },
    setUnitStatus(state, { payload: { unitPowerLimitList, unitResultList, updateTime } }) {
      return { ...state, unitPowerLimitList, unitResultList, statusUpdateTime: updateTime };
    },
  },
  effects: {
    /**
     * 加载用户有权限的场站树列表
     * @param {*} param0
     * @param {*} param1
     * @returns
     */
    *getStationLevelThreeEffect({ payload }, { call, put, select }) {
      yield put({ type: 'setAddLoadingNum' });
      let {
        configure: { menuCode },
      } = yield select((_) => _.global);
      const res = yield call(queryMarketList, menuCode);
      yield put({ type: 'setSubLoadingNum' });

      if (res?.statusCode === HttpCode.SUCCESS) {
        const { treeOptions } = getTreeByCodes(['market', 'group', 'station'], res.json);
        let data = treeOptions;
        // 处理数据权限
        if (!data) {
          TRMessage.error(messageConstant.NO_UNIT_PERMISSION_WARNING_MESSAGE);
          return;
        }

        // 当前过滤为山西
        let stationTree =
          data.filter((item) => {
            return item?.provinceId === '14';
          })[0]?.children || [];

        // let stationTree = data[0]?.children || [];

        // 处理数据。为了适用子组件，所有公司及场站增加key title字段，key = value title = label
        stationTree.forEach((company) => {
          // company?.value && (company.key = company.value);
          company?.label && (company.title = company.label);
          (company?.children || []).forEach((station) => {
            station?.value && (station.key = station.value);
            station?.label && (station.title = station.label);
          });
        });

        let stations = [];

        stationTree.forEach((company) =>
          (company?.children || []).forEach((station) => stations.push(station)),
        );

        yield put({ type: 'setComponentUnitList', payload: stations });
        yield put({ type: 'setUnitTree', payload: stationTree });
      } else {
        TRMessage.error(
          res.message || messageConstant.GET_STATIONS_LEVEL_THREE_DEFAULT_ERROR_MESSAGE,
        );
      }
    },
    /**
     * 获取带申报方案总览列表
     * @param {*} param0
     * @param {*} param1
     * @returns
     */
    *fetchProgramOverviewList({ payload }, { call, put, select }) {
      let {
        globalSequence: {
          current: { tradeSequenceId },
        },
      } = yield select((_) => _.rollingBatch);
      let {
        configure: { menuCode },
      } = yield select((_) => _.global);

      yield put({ type: 'setAddLoadingNum' });
      const { statusCode, message, data } = yield call(
        fetchOverviewProgramToBeSubmited,
        menuCode,
        tradeSequenceId,
      );
      yield put({ type: 'setSubLoadingNum' });
      if (statusCode === HttpCode.SUCCESS) {
        data.length ? yield put({ type: 'setProgramOverviewList', payload: data }) : null;
        return;
      }
      TRMessage.error(message || messageConstant.FETCH_PROGRAM_OVERVIEW_DEFAULT_ERROR_MESSAGE);
    },
    /**
     * 每隔30s同步交易中心时间
     * @param {*} param0
     * @param {*} param1
     */
    *fetchTradeTimeEffect({ payload }, { call, put, select }) {
      const { statusCode, message, data } = yield call(fetchTradeTime);
      if (statusCode === HttpCode.SUCCESS) {
        yield put({ type: 'setTradeCenterTime', payload: moment(data.time) });
        yield put({ type: 'updateTradeTimeEffect' });
      } else {
        TRMessage.error(message || messageConstant.FETCH_TRADE_CENTER_TIME_DEFAULT_ERROR_MESSAGE);
      }
      yield delay(30 * 1000);
      yield put({ type: 'fetchTradeTimeEffect' });
    },
    /**
     * 每隔一秒更新交易中心时间
     * @param {*} param0
     * @param {*} param1
     */
    *updateTradeTimeEffect({ payload }, { call, put, select }) {
      yield delayClear(1 * 1000);
      let currentState = yield select((_) => _.rollingBatch);
      let time = moment(currentState.tradeCenterTime);
      time.add(1, 's');
      yield put({ type: 'setTradeCenterTime', payload: moment(time) });
      yield put({ type: 'updateTradeTimeEffect' });
    },
    /**
     * 获取当下或未来最近的序列信息
     * @param {*} param0
     * @param {*} param1
     */
    *fetchSequence({ payload }, { call, put }) {
      yield put({ type: 'setAddLoadingNum' });
      const { statusCode, message, data } = yield call(fetchSequencesFuture);
      yield put({ type: 'setSubLoadingNum' });

      if (statusCode === HttpCode.SUCCESS) {
        const { tradeDate, sequenceList } = data;
        yield put({
          type: 'setGlobalSequence',
          payload: {
            date: tradeDate ? moment(tradeDate) : new moment(),
            dataList: emptyIfNotExist(sequenceList),
            current: {},
            selected: findFirstIfArr(sequenceList),
          },
        });
      } else {
        TRMessage.error(message || messageConstant.FETCH_SEQUENCES_DEFAULT_ERROR_MESSAGE);
      }
    },
    /**
     * 根据日期获取序列信息
     * @param {{tradeDate:moment}} param0
     * @param {*} param1
     */
    *fetchSequenceByDate({ payload: { tradeDate } }, { call, put }) {
      yield put({ type: 'setAddLoadingNum' });
      const { statusCode, message, data } = yield call(
        fetchSequences,
        tradeDate.format(SEQUENCE_TRADE_TIME_PATTERN),
      );
      yield put({ type: 'setSubLoadingNum' });

      if (statusCode === HttpCode.SUCCESS) {
        const { sequenceList } = data;
        yield put({
          type: 'setGlobalSequence',
          payload: {
            date: tradeDate,
            dataList: emptyIfNotExist(sequenceList),
            selected: findFirstIfArr(sequenceList),
          },
        });
      } else {
        TRMessage.error(message || messageConstant.FETCH_SEQUENCE_BY_DATE_DEFAULT_ERROR_MESSAGE);
      }
    },
    /**
     * 修改序列id
     * @param {*} param0
     * @param {*} param1
     */
    *changeCurrentSequence({ payload: { sequenceId } }, { put, select }) {
      let {
        globalSequence: { dataList },
      } = yield select((_) => _.rollingBatch);
      yield put({
        type: 'setGlobalSequence',
        payload: {
          selected: dataList.find(({ tradeSequenceId }) => tradeSequenceId === sequenceId),
        },
      });
    },
    /**
     * 处理搜索按钮点击
     * @param {*} param0
     * @param {*} param1
     */
    *handleSearchEffect({ payload }, { put, select }) {
      let {
        globalSequence: { selected },
      } = yield select((_) => _.rollingBatch);
      if (selected.tradeSequenceId) {
        yield put({ type: 'setHasModified', payload: false });

        yield put({ type: 'setGlobalSequence', payload: { current: clone(selected) } });

        //获取序列限价
        yield put({ type: 'fetchSequencePriceLimit' });

        // 获取方案列表
        yield put({ type: 'fetchProgramList' });

        yield put({ type: 'setShowMain', payload: true });
      } else {
        TRMessage.warning(messageConstant.NO_SEQUENCE_WARNING_MESSAGE);
        yield put({ type: 'setShowMain', payload: false });
      }
    },
    /**
     * 获取序列的限价信息
     * @param {*} param0
     * @param {*} param1
     */
    *fetchSequencePriceLimit({ payload }, { call, put, select }) {
      let {
        globalSequence: {
          selected: { tradeSequenceId },
        },
        priceLimitInfo,
      } = yield select((_) => _.rollingBatch);
      // 限价是不会变化的，不需要重复获取
      if (objHasElement(priceLimitInfo[tradeSequenceId])) {
        return;
      }
      yield put({ type: 'setAddLoadingNum' });
      const { statusCode, message, data } = yield call(fetchSequencesLimit, tradeSequenceId);
      yield put({ type: 'setSubLoadingNum' });

      if (statusCode === HttpCode.SUCCESS) {
        const { priceLimitList } = data;
        let payload = { [tradeSequenceId]: {} };
        priceLimitList.forEach((limitItem) => {
          payload[tradeSequenceId][limitItem.hourOrder] = limitItem;
        });
        yield put({ type: 'setPriceLimitInfo', payload });
        return;
      }
      TRMessage.error(message || messageConstant.FETCH_SEQUENCE_LIMIT_DEFAULT_ERROR_MESSAGE);
    },
    /**
     * 获取当下序列的方案列表
     * @param {*} param0
     * @param {*} param1
     * @returns
     */
    *fetchProgramList({ payload }, { call, put, select }) {
      yield put({ type: 'setHasModified', payload: false });
      yield put({ type: 'setLatestOperateLog', payload: {} });
      let {
        globalSequence: {
          selected: { tradeSequenceId },
        },
      } = yield select((_) => _.rollingBatch);
      let {
        configure: {
          currentUser: { name },
        },
      } = yield select((_) => _.global);

      yield put({ type: 'setAddLoadingNum' });
      const { statusCode, message, data } = yield call(fetchPrograms, tradeSequenceId);
      yield put({ type: 'setSubLoadingNum' });

      if (statusCode === HttpCode.SUCCESS) {
        let { programList } = data;
        // 过滤掉被删除的
        programList = (programList || []).filter(({ status }) => status !== PROGARM_STATUS.DEL);
        yield put({ type: 'setProgramList', payload: programList });

        // 查询用户默认方案
        const programId = payload?.programId
          ? payload.programId
          : findDefaultProgramId(programList, name);
        // 加载方案内容
        yield put({ type: 'fetchProgramDetail', payload: { programId } });
        return;
      }
      TRMessage.error(message || messageConstant.FETCH_PROGRAM_LIST_DEFAULT_ERROR_MESSAGE);
    },
    /**
     * 获取方案详情
     * @param {*} param0
     * @param {*} param1
     */
    *fetchProgramDetail({ payload: { programId } }, { call, put, select }) {
      if (!programId) {
        return;
      }
      // 查询用户有权限看到的场站状态，就是获取场站限额
      yield put({ type: 'fetchUnitStatusInfo' });
      yield put({ type: 'setSelectedRowKeys', payload: [] });
      // 获取最新的日志
      yield put({ type: 'fetchCurrentProgramLog', payload: { programId } });

      let {
        configure: { menuCode, buttonPermissions },
      } = yield select((_) => _.global);
      let { programList } = yield select((_) => _.rollingBatch);

      yield put({ type: 'setAddLoadingNum' });
      const { statusCode, message, data } = yield call(fetchHourOrderInfo, menuCode, programId);
      yield put({ type: 'setSubLoadingNum' });

      if (statusCode === HttpCode.SUCCESS) {
        let {
          unitList,
          deletePermission: remove,
          editPermission: modify,
          hourOrderList,
          programInfo,
        } = data;
        yield put({ type: 'setCurrentUnitList', payload: unitList });
        // 方案能被查到一定有场站，但是不一定有时段,如果没有则赋值默认时段
        if (!arrHasElement(hourOrderList)) {
          hourOrderList = getNewProgramInfo('').hourOrderList;
        }
        yield put({ type: 'setCurrentProgramHourOrderList', payload: hourOrderList });
        yield put({ type: 'setCurrentProgramInfo', payload: programInfo });
        yield put({
          type: 'setCurrentProgramPermisson',
          payload: { remove, modify, ...getButtonPermission(buttonPermissions) },
        });

        yield put({
          type: 'setProgramList',
          payload: programList.map((item) => {
            if (item.id == programId) {
              // 更新当前方案信息
              return { ...item, remove, ...programInfo };
            } else {
              return { ...item };
            }
          }),
        });
        return;
      }
      TRMessage.error(message || messageConstant.FETCH_PROGRAM_DETAIL_DEFAULT_ERROR_MESSAGE);
    },
    /**
     * 获取当前方案最新日志
     * @param {*} param0
     * @param {*} param1
     */
    *fetchCurrentProgramLog({ payload: { programId } }, { call, put, select }) {
      yield put({ type: 'setAddLoadingNum' });
      const { statusCode, message, data } = yield call(fetchLatestLog, programId);
      yield put({ type: 'setSubLoadingNum' });

      if (statusCode === HttpCode.SUCCESS) {
        yield put({ type: 'setLatestOperateLog', payload: data.latestOperateLog });
        return;
      }
      TRMessage.error(message || messageConstant.FETCH_LATEST_LOG_DEFAULT_ERROR_MESSAGE);
    },
    /**
     * 查询场站的状态信息
     * @param {*} param0
     * @param {*} param1
     */
    *fetchUnitStatusInfo({ payload }, { call, put, select }) {
      let {
        globalSequence: {
          selected: { tradeSequenceId },
        },
      } = yield select((_) => _.rollingBatch);
      let {
        configure: { menuCode },
      } = yield select((_) => _.global);

      yield put({ type: 'setAddLoadingNum' });
      const { statusCode, message, data } = yield call(fetchUnitStatus, menuCode, tradeSequenceId);
      yield put({ type: 'setSubLoadingNum' });

      if (statusCode === HttpCode.SUCCESS) {
        let { unitPowerLimitList, unitResultList, updateTime } = data;
        yield put({
          type: 'setUnitStatus',
          payload: { unitPowerLimitList, unitResultList, updateTime },
        });
        // 整理限额信息，方便组件使用
        yield put({
          type: 'setPowerLimitInfo',
          payload: getUnitPowerLimitInfo(unitPowerLimitList),
        });
        return;
      }
      TRMessage.error(message || messageConstant.FETCH_UNITS_STATUS_DEFAULT_ERROR_MESSAGE);
    },
    /**
     * 切换方案
     * @param {*} param0
     * @param {*} param1
     */
    *changeCurrentProgram({ payload: { programId } }, { call, put, select }) {
      let {
        currentProgramInfo: { status },
        programList,
      } = yield select((_) => _.rollingBatch);
      // 如果当前方案为新增方案,则移除改方案
      if (status === PROGARM_STATUS.CREATE) {
        yield put({
          type: 'setProgramList',
          payload: programList.filter(({ status }) => status !== PROGARM_STATUS.CREATE),
        });
      }
      yield put({ type: 'fetchProgramDetail', payload: { programId } });
    },

    /**
     * 修改方案内容
     * @param {*} param0 modifyInfo: key→时段 ，value→要修改的内容
     * @param {*} param1
     */
    *modifyProgramInfoContent({ payload: { modifyInfo } }, { select, put }) {
      let { currentProgramHourOrderList: hourOrderList } = yield select((_) => _.rollingBatch);
      // 修改内容替换原内容
      yield put({
        type: 'setCurrentProgramHourOrderList',
        payload: hourOrderList.map((item) =>
          modifyInfo[item.hourOrder] ? { ...item, ...modifyInfo[item.hourOrder] } : item,
        ),
      });
      yield put({ type: 'setHasModified', payload: true });
    },
    /**
     * 修改方案调剂
     * @param {*} param0
     * @param {*} param1
     */
    *modifyProgramInfoAdjust({ payload }, { select, put }) {
      let { currentProgramInfo } = yield select((_) => _.rollingBatch);
      yield put({
        type: 'setCurrentProgramInfo',
        payload: { ...currentProgramInfo, ...{ adjustFlag: !currentProgramInfo.adjustFlag } },
      });
    },
    /**
     * 修改方案的交易单元
     * @param {*} param0
     * @param {*} param1
     * @returns
     */
    *modifyProgramInfoUnits({ payload: { unitList } }, { call, put, select }) {
      let {
        configure: { menuCode },
      } = yield select((_) => _.global);
      let {
        currentProgramInfo,
        currentUnitList: originUnitList,
        globalSequence: {
          current: { tradeSequenceId },
        },
      } = yield select((_) => _.rollingBatch);
      //  如果选择的场站没有变化，则不处理
      if (selectedUnitsHasModified(originUnitList, unitList)) {
        return;
      }
      let programId = currentProgramInfo.id === '-1' ? null : currentProgramInfo.id;
      yield put({ type: 'setAddLoadingNum' });
      const { statusCode, message, data } = yield call(
        saveUnits,
        menuCode,
        currentProgramInfo.title,
        tradeSequenceId,
        unitList.map((item) => item.unitId),
        programId,
      );
      yield put({ type: 'setSubLoadingNum' });

      switch (statusCode) {
        case HttpCode.SUCCESS:
          yield put({ type: 'setHasModified', payload: false });
          yield put({ type: 'fetchProgramList', payload: { programId: data?.id } });
          break;
        case PROGRAM_NOT_EXIST_HTTP_CODE:
          TRMessage.error(messageConstant.PROGRAM_NOT_EXIST_ERROR_MESSAGE);
          // 重新查询序列下的方案
          yield put({ type: 'handleSearchEffect' });
          break;
        case PROGRAM_LOCKED_HTTP_CODE:
          TRMessage.error(messageConstant.PROGRAM_LOCKED_ERROR_MESSAGE);
          // 重新查询序列下的方案
          yield put({ type: 'setHasModified', payload: false });
          yield put({ type: 'fetchProgramDetail', payload: { programId } });
          break;
        default:
          TRMessage.error(message || messageConstant.SAVE_UNITS_DEFAULT_ERROR_MESSAGE);
          break;
      }
    },
    /**
     * 删除方案
     * @param {*} param0
     * @param {*} param1
     */
    *deleteProgram({ payload: { programId } }, { call, put, select }) {
      let {
          programList,
          currentProgramInfo: { id: currentProgramId, status: currentProgramStatus },
        } = yield select((_) => _.rollingBatch),
        removeSuccess = false;
      // 如果是新增方案,因为新增方案只有可能是当前方案，不可能是其他方案
      if (programId === currentProgramId && currentProgramStatus == PROGARM_STATUS.CREATE) {
        let newProgramList = programList.filter(({ id }) => id !== programId);
        yield put({ type: 'setProgramList', payload: newProgramList });
        removeSuccess = true;
      } else {
        // 如果非新增方案，则调用删除接口
        let {
          configure: { menuCode },
        } = yield select((_) => _.global);
        yield put({ type: 'setAddLoadingNum' });
        const { statusCode, message } = yield call(deleteProgram, menuCode, programId);
        yield put({ type: 'setSubLoadingNum' });

        switch (statusCode) {
          case HttpCode.SUCCESS:
            removeSuccess = true;
            break;
          case PROGRAM_NOT_EXIST_HTTP_CODE:
            TRMessage.warning(messageConstant.PROGRAM_ALREADY_DELETE_ERROR_MESSAGE);
            // 重新查询序列下的方案
            yield put({ type: 'handleSearchEffect' });
            break;
          case PROGRAM_LOCKED_HTTP_CODE:
            TRMessage.error(messageConstant.PROGRAM_LOCKED_DELETE_ERROR_MESSAGE);
            // 重新查询序列下的方案
            yield put({ type: 'setHasModified', payload: false });
            yield put({ type: 'fetchProgramDetail', payload: { programId } });
            break;
          default:
            TRMessage.error(message || messageConstant.DELETE_PROGRAM_DEFAULT_ERROR_MESSAGE);
            break;
        }
      }
      // 如果删除成功且删除的当前浏览的id，则重新查询方案列表
      if (removeSuccess) {
        TRMessage.success(messageConstant.DELETE_PROGRAM_DEFAULT_SUCCESS_MESSAGE);
        if (programId == currentProgramId) {
          yield put({ type: 'handleSearchEffect' });
        }
      }
    },
    /**
     * 新增方案
     * @param {*} param0
     * @param {*} param1
     */
    *initNewProgramAndChoose({ payload }, { put, select }) {
      // 查询用户有权限看到的场站状态，就是获取场站限额
      yield put({ type: 'fetchUnitStatusInfo' });
      let {
        configure: {
          currentUser: { name },
          buttonPermissions,
        },
      } = yield select((_) => _.global);
      let { programList } = yield select((_) => _.rollingBatch);
      // 获取新的方案名称
      let newProgramName = getNewProgramName(name, programList);
      // 构造新的方案信息
      let { programInfo, hourOrderList } = getNewProgramInfo(newProgramName);

      yield put({ type: 'setAddLoadingNum' });
      yield put({ type: 'setProgramList', payload: [...programList, programInfo] });
      yield put({ type: 'setCurrentProgramHourOrderList', payload: hourOrderList });
      yield put({
        type: 'setCurrentProgramPermisson',
        payload: { remove: true, modify: true, ...getButtonPermission(buttonPermissions) },
      });
      yield put({ type: 'setCurrentProgramInfo', payload: programInfo });
      yield put({ type: 'setCurrentUnitList', payload: [] });
      yield put({ type: 'setLatestOperateLog', payload: {} });
      yield put({ type: 'setModified', payload: true });
      yield put({ type: 'setSubLoadingNum' });
    },
    /**
     * 提交方案
     * @param {*} param0
     * @param {*} param1
     */
    *submitProgram({ payload: { operateType, timelySubmitTime } }, { put, select, call }) {
      let {
          configure: { menuCode },
        } = yield select((_) => _.global),
        {
          currentProgramHourOrderList: intervals,
          powerLimitInfo,
          priceLimitInfo,
          currentUnitList,
          currentProgramInfo: { id: programId, adjustFlag },
          globalSequence: {
            current: { tradeSequenceId: sequenceId },
          },
          date: sequenceDate,
        } = yield select((_) => _.rollingBatch),
        paramTimelySubmitTime = timelySubmitTime
          ? `${moment(sequenceDate).format('YYYY-MM-DD')} ${timelySubmitTime.format('HH:mm:ss')}`
          : null,
        limitInfo = get24HourLimitList(powerLimitInfo, currentUnitList, priceLimitInfo[sequenceId]),
        msg = '';
      yield put({ type: 'setAddLoadingNum' });
      const { statusCode, message } = yield call(
        submit,
        intervals.map((item) => ({
          ...item,
          sellPowerLimit: limitInfo[item.hourOrder - 1].sellLimit,
          buyPowerLimit: limitInfo[item.hourOrder - 1].buyLimit,
        })),
        menuCode,
        operateType,
        programId,
        sequenceId,
        paramTimelySubmitTime,
        adjustFlag,
      );
      yield put({ type: 'setSubLoadingNum' });

      switch (statusCode) {
        case HttpCode.SUCCESS:
          yield put({ type: 'setHasModified', payload: false });
          yield put({ type: 'fetchProgramList', payload: { programId: programId } });
          switch (operateType) {
            case 0:
              msg = '保存方案成功';
              break;
            case 1:
              msg = '定时申报成功';
              break;
            case 2:
              msg = '立即申报成功';
              break;
          }
          TRMessage.success(message || msg);
          return;
        case PROGRAM_LOCKED_HTTP_CODE:
          TRMessage.error(messageConstant.PROGRAM_LOCKED_ERROR_MESSAGE);
          // 重新查询序列下的方案
          yield put({ type: 'setHasModified', payload: false });
          yield put({ type: 'fetchProgramDetail', payload: { programId } });
          return;
        case PROGRAM_NOT_EXIST_HTTP_CODE:
          TRMessage.error(messageConstant.PROGRAM_NOT_EXIST_ERROR_MESSAGE);
          // 重新查询序列下的方案
          yield put({ type: 'handleSearchEffect' });
          return;
        default:
          switch (operateType) {
            case 0:
              msg = '保存方案失败';
              break;
            case 1:
              msg = '定时申报失败';
              break;
            case 2:
              msg = '立即申报失败';
              break;
          }
          TRMessage.error(message || msg);
      }
    },
    *cancelTimelySubmit({ payload }, { put, select, call }) {
      let {
        currentProgramInfo: { id: programId },
      } = yield select((_) => _.rollingBatch);
      let {
        configure: { menuCode },
      } = yield select((_) => _.global);
      yield put({ type: 'setAddLoadingNum' });
      const { statusCode, message } = yield call(cancelTimelySubmit, menuCode, programId);
      yield put({ type: 'setSubLoadingNum' });
      switch (statusCode) {
        case HttpCode.SUCCESS:
          TRMessage.success(messageConstant.CANCEL_TIMELY_SUBMIT_SUCCESS_MESSAGE);
          yield put({ type: 'fetchProgramList', payload: { programId } });
          break;
        // 方案不存在
        case PROGRAM_NOT_EXIST_HTTP_CODE:
          TRMessage.error(messageConstant.PROGRAM_ALREADY_DELETE_ERROR_MESSAGE);
          yield put({ type: 'fetchProgramList' });
          break;
        // 方案未被定时
        case PROGRAM_NOT_TIMELY_HTTP_CODE:
          TRMessage.error(messageConstant.PROGRAM_NOT_TIMELY_TIMELY_ERROR_MESSAGE);
          yield put({ type: 'fetchProgramList' });
          break;
        // 默认定时失败
        default:
          TRMessage.error(message || messageConstant.CANCEL_TIMELY_SUBMIT_ERROR_MESSAGE);
          break;
      }
    },
    /**
     * 异步更新挂单状态
     * @param {*} param0
     * @param {*} param1
     * @returns
     */
    *asyncUpdateStatus({ payload }, { put, select, call }) {
      let {
          configure: { menuCode },
        } = yield select((_) => _.global),
        {
          globalSequence: {
            current: { tradeSequenceId },
          },
        } = yield select((_) => _.rollingBatch);

      yield put({ type: 'setAddLoadingNum' });
      const { statusCode, message } = yield call(updateStatus, menuCode, tradeSequenceId);
      yield put({ type: 'setSubLoadingNum' });

      if (statusCode === HttpCode.SUCCESS) {
        TRMessage.success(messageConstant.ASYNC_UPDATE_UNIT_STATUS_SUCCESS_MESSAGE);
      } else {
        TRMessage.error(message || messageConstant.ASYNC_UPDATE_UNIT_STATUS_ERROR_MESSAGE);
      }
    },
  },
};
